package com.quwan.chat;

import com.quwan.chat.handle.ChatMsgHandler;
import com.quwan.chat.properties.NettyProperties;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import java.net.InetAddress;


/**
 * @author quan
 * @date 2021-09-01 14:50
 */

//@Order
//@Component
//@EnableAsync
public class NettyWebSocketServer implements CommandLineRunner{
    private static final Logger log = LoggerFactory.getLogger(NettyWebSocketServer.class);

    @Autowired
    NettyProperties properties;

    @Autowired
    ChatMsgHandler chatMsgHandler;

//    @Async
    @Override
    public void run(String... args) throws Exception {
        EventLoopGroup main = new NioEventLoopGroup(properties.getMain());
        EventLoopGroup work = new NioEventLoopGroup(properties.getWork());
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap()
                    .group(main, work)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, properties.getMaxTask())
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //http解码器
                            pipeline.addLast(new HttpServerCodec());
                            //块数据写出处理器
                            pipeline.addLast(new ChunkedWriteHandler());
                            //数据分段处理器
                            pipeline.addLast(new HttpObjectAggregator(properties.getContentLength()));
                            //ws协议 处理器
                            pipeline.addLast(new WebSocketServerProtocolHandler(properties.getPath(), null, true, 65536));
                            //业务处理
                            pipeline.addLast(chatMsgHandler);
                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(properties.getPort()).sync();
            log.info("\n-----NettyWebSocketServer start" +
                            "\n\t port:\t{}" +
                            "\n\t connect:\tws://{}:{}{}",
                    properties.getPort(), InetAddress.getLocalHost().getHostAddress()
                    , properties.getPort(), properties.getPath());

            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            main.shutdownGracefully();
            work.shutdownGracefully();
        }


    }


}
